﻿using QInjection.Injector.Contracts;
using Roslyn.Compilers.CSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace QInjection.Injector
{
    internal class RulesSet
    {
        private Dictionary<Type, Dictionary<Restriction, List<RuleData>>> _noderules_set;
        private RuleNodeMap _rulenodemap;

        internal RulesSet()
        {
            _noderules_set = new Dictionary<Type, Dictionary<Restriction, List<RuleData>>>();
            _rulenodemap = new RuleNodeMap();
        }

        internal void Add(Node node, Type ntype, RuleData rdata)
        {
            if (_rulenodemap.SupportRuleOnNode(node, rdata.Rule))
            {
                if (!_noderules_set.ContainsKey(ntype))
                    _noderules_set[ntype] = new Dictionary<Restriction, List<RuleData>>();
                if (!_noderules_set[ntype].ContainsKey(rdata.Rule))
                    _noderules_set[ntype][rdata.Rule] = new List<RuleData>();
                _noderules_set[ntype][rdata.Rule].Add(rdata);
            }
        }
        
        internal void Validate(Type ntype, SyntaxNode node)
        {
            if (_noderules_set.ContainsKey(ntype))
            {
                var rules = _noderules_set[ntype];
                foreach (var r in rules)
                {
                    if (ntype == typeof(BinaryExpressionSyntax))
                        RuleValidator.Validate(ntype, (BinaryExpressionSyntax)node, r.Key, r.Value);
                    else if (ntype == typeof(LiteralExpressionSyntax))
                        RuleValidator.Validate(ntype, (LiteralExpressionSyntax)node, r.Key, r.Value);
                    else if (ntype == typeof(IdentifierNameSyntax))
                        RuleValidator.Validate(ntype, (IdentifierNameSyntax)node, r.Key, r.Value);
                    else if (ntype == typeof(ParameterSyntax))
                        RuleValidator.Validate(ntype, (ParameterSyntax)node, r.Key, r.Value);
                    else if (ntype == typeof(MemberAccessExpressionSyntax))
                        RuleValidator.Validate(ntype, (MemberAccessExpressionSyntax)node, r.Key, r.Value);
                    else if (ntype == typeof(InvocationExpressionSyntax))
                        RuleValidator.Validate(ntype, (InvocationExpressionSyntax)node, r.Key, r.Value);
                    else if (ntype == typeof(ArgumentSyntax))
                        RuleValidator.Validate(ntype, (ArgumentSyntax)node, r.Key, r.Value);
                    else if (ntype == typeof(PrefixUnaryExpressionSyntax))
                        RuleValidator.Validate(ntype, (PrefixUnaryExpressionSyntax)node, r.Key, r.Value);
                    else if (ntype == typeof(PostfixUnaryExpressionSyntax))
                        RuleValidator.Validate(ntype, (PostfixUnaryExpressionSyntax)node, r.Key, r.Value);
                    else if (ntype == typeof(ConditionalExpressionSyntax))
                        RuleValidator.Validate(ntype, (ConditionalExpressionSyntax)node, r.Key, r.Value);
                    //else
                    //    throw new Exception("Unexpected node type");
                }
            }
        }
    }
}
